/*************************************************************************
 Copyright (C) Unpublished Unis Software, Inc. All rights reserved.
 Unis Software, Inc., Confidential and Proprietary.

 This software is subject to copyright protection
 under the laws of the Public of China and other countries.

 Unless otherwise explicitly stated, this software is provided
 by Unis "AS IS".
 *************************************************************************/
package com.unis.web.attach;

import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import com.unis.common.ui.jqGrid.GridUIMapper;
import com.unis.common.util.DetectUtil;
import com.unis.common.util.TemplateUtil;
import com.unis.common.util.TimeUtil;
import com.unis.common.util.WebUtil;
import com.unis.model.BaseModel;
import com.unis.model.attach.Attachment;
import com.unis.service.attach.AttachmentService;

/**
 * @author CSJ (email:raulcsj@163.com)
 * @since 2013-03-07
 */
@Controller
@RequestMapping("/attachment")
public class AttachmentController {

    private AttachmentService attachmentService;

    /****************************************
     * Insert a instace of Attachment
     ****************************************/
    @RequestMapping("/insert")
    @ResponseBody
    public Object insertAttachment(@RequestBody Attachment attachment) throws Exception {
        attachment.setStatmentId("Attachment.insert");
        String status = "failure";
        attachmentService.insert(attachment);
        status = "success";
        return status;
    }

    /****************************************
     * Update a instace of Attachment
     ****************************************/
    @RequestMapping("/update")
    @ResponseBody
    public Object update(@RequestBody Attachment attachment) throws Exception {
        attachment.setStatmentId("Attachment.update");
        String status = "failure";
        attachmentService.update(attachment);
        status = "success";
        return status;
    }

    /****************************************
     * Delete a instace of Attachment
     ****************************************/
    @RequestMapping("/delete")
    @ResponseBody
    public Object delete(@RequestBody Attachment attachment) throws Exception {
        attachment.setStatmentId("Attachment.delete");
        String status = "failure";
        attachmentService.batchDelete(attachment);
        status = "success";
        return status;
    }

    /****************************************
     * Query instaces of Attachment
     ****************************************/
    @RequestMapping("/queryAsList")
    @ResponseBody
    public Object queryAsList(HttpServletRequest request) throws Exception {
        Map<String, Object> paramMap = WebUtil.getParamsMapFromRequest(request);
        Attachment attachment = new Attachment();
        attachment.setStatmentId("Attachment.queryAsList");
        BeanUtils.populate(attachment, paramMap);
        Map<String, Object> pageMap = GridUIMapper.process(paramMap);
        BeanUtils.populate(attachment, pageMap);
        List<BaseModel> attachmentList = attachmentService.queryAsList(attachment);
        Map<String, Object> renderMap = GridUIMapper.render(attachment, attachmentList);
        return renderMap;
    }

    /****************************************
     * Query a instaces of Attachment
     ****************************************/
    @RequestMapping("/queryAsObject")
    @ResponseBody
    public BaseModel queryAsObject(@RequestBody Attachment attachment) throws Exception {
        attachment.setStatmentId("Attachment.queryAsObject");
        return attachmentService.queryAsObject(attachment);
    }

    @RequestMapping("/preview")
    public void previewImg(Attachment attachment, HttpServletResponse resp) throws Exception {
        attachment.setStatmentId("Attachment.queryAsObject");
        attachment = (Attachment) attachmentService.queryAsObject(attachment);
        byte[] body = attachment.getFilebody();

        File tmp = new File(attachment.getFilename());
        FileUtils.writeByteArrayToFile(tmp, body);
        BufferedImage image = ImageIO.read(tmp);
        int width = image.getWidth();
        int height = image.getHeight();
        double ratio = 0.;
        Image tmpIm = image.getScaledInstance(50, 50, BufferedImage.SCALE_SMOOTH);
        if (height > 50 || width > 50) {
            if (height > width) {
                ratio = 50. / height;
            } else {
                ratio = 50. / width;
            }
        }
        AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
        tmpIm = op.filter(image, null);

        resp.setHeader("Content-Type", "image/*");
        resp.setHeader("Connection", "close");
        resp.setContentLength(body.length);

        OutputStream out = resp.getOutputStream();
        ImageIO.write((RenderedImage) tmpIm, "png", out);
        out.flush();
        out.close();
        FileUtils.deleteQuietly(tmp);
    }

    @RequestMapping(value = "/active", method = RequestMethod.HEAD)
    public ResponseEntity<String> attachServiceActive() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("success", "true");
        headers.set("message", "Service works well!!");
        return new ResponseEntity<String>("The String ResponseBody with custom header", headers, HttpStatus.OK);
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ResponseEntity<String> upload(HttpServletRequest request, @RequestParam MultipartFile[] files)
            throws Exception {
        Map<String, Object> paramMap = WebUtil.getParamsMapFromRequest(request);

        String statmentId = "Attachment.insert";
        Object catalogid = paramMap.get("catalogid");
        Object creatorid = paramMap.get("creatorid");

        List<BaseModel> attachList = new ArrayList<BaseModel>();

        for (MultipartFile uploadFile : files) {
            Attachment attachment = new Attachment();
            attachment.setStatmentId(statmentId);
            attachment.setFileid(TemplateUtil.genUUID());
            attachment.setFilename(uploadFile.getOriginalFilename());
            attachment.setFilesize(uploadFile.getSize());
            attachment.setFilebody(uploadFile.getBytes());
            attachment.setFiletype(DetectUtil.getRealType4Byte(uploadFile.getBytes()));
            attachment.setCatalogid(catalogid.toString());
            attachment.setCreatorid(creatorid.toString());
            attachment.setCreatetime(TimeUtil.getNow());

            attachList.add(attachment);
        }
        attachmentService.batchInsert(attachList);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_PLAIN);
        return new ResponseEntity<String>("success", headers, HttpStatus.OK);
    }

    @RequestMapping("/download")
    public ResponseEntity<byte[]> download(Attachment attachment, HttpServletResponse response) throws Exception {
        attachment.setStatmentId("Attachment.queryAsObject");
        attachment = (Attachment) attachmentService.queryAsObject(attachment);
        String filename = URLEncoder.encode(attachment.getFilename(), "utf-8");
        byte[] body = attachment.getFilebody();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentLength(body.length);
        headers.set("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        return new ResponseEntity<byte[]>(body, headers, HttpStatus.OK);
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<String> handleException(Exception ex, HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_PLAIN);
        return new ResponseEntity<String>(ex.getMessage(), headers, HttpStatus.EXPECTATION_FAILED);
    }

    @RequestMapping("/page")
    public String forword() {
        return "attach/attachmentList";
    }

    @Resource
    public void setAttachmentService(AttachmentService attachmentService) {
        this.attachmentService = attachmentService;
    }
}
